// treetable.js

(function(jq){
  var opts = {openImg: "/classpath/treetable/themes/default/tv-collapsable.gif", shutImg: "/classpath/treetable/themes/default/tv-expandable.gif", lastOpenImg: "/classpath/treetable/themes/default/tv-collapsable-last.gif", lastShutImg: "/classpath/treetable/themes/default/tv-expandable-last.gif"};
  var contextRoot ;
  var urlAjax ;
  var key ;

  jq.fn.treetable = function(_contextRoot,_urlAjax, _key){
    contextRoot = _contextRoot ;
    urlAjax = _urlAjax ;
    key = _key ;

    bindClick () ;
  };
  
  // 
  bindClick = function () {
    jq (".parimg").each(function(i){
      var $this = jq(this);
      $this.unbind ('click') ;
      $this.click(function() {
          var tr_row = $this.parents("tr") ;
          expandOrCollapse (tr_row) ;
      }) ;
    });
    
    jq(".ajaximg").each(function(i){
      var $this = jq(this);
      $this.unbind ('click') ;
      $this.click(function () {
          var img = $this ;
          retrieveRowWithAjax (img) ;
      }) ;
    });
  }
 
  //
  
  retrieveRowWithAjax = function(imgClicked){
    var tr_row = imgClicked.parents("tr") ;
    var num = tr_row.attr("id") ; // id of the row
    var parentId = parseParent (num) ;
    var _type = parseType (num) ;
        
    // alert ("retrieveRowWithAjax: " + num + " type: " + _type) ;

    // read tree context from the html 
    var arr = imgClicked.prevAll ("img").map (function (i, img) {
      var $img = jq (img) ;
      var src = $img.attr ("src") ;

      if (src.indexOf ("vertline.gif") != -1)
        return ("1") ;
      else
        return ("0") ;
    }).get () ;
          
    // determina si la fila es la ultima en su nivel
    // nota: funciona pq todavia no tiene descendientes
    // TO-DO: cambiar por mirar la imagen asociada
    var isLast = true ;
    tr_row.nextAll ("tr").each (function () {
      var nextNum = jq (this).attr ("id") ;
      var nextParentId = parseParent (nextNum) ;
      var nextType = parseType (nextNum) ;
          
      // todas las filas en el mismo nivel comparten un mismo tipo
      if (nextType != _type)
        return (false) ;
          
      if (nextParentId == parentId)
      {
        isLast = false ;
        return (false) ;
      }
    });

    arr = arr.reverse () ;

    if (isLast)
      arr.push ("0") ;
    else
      arr.push ("1") ;
        
    var imgContext = arr.join ("") ;
            
    var _data = num + "_context_" + imgContext ;
        
    jq.ajax (
              {
                url : urlAjax,
                data : key + "=" + _data,
                type : 'POST',
                dataType : 'script',
                timeout : 140000,
                cache : false,
                complete : reBindClick
              }
            );

    // 
    imgClicked.attr("src", function(){
      var ret = (this.src.lastIndexOf (opts.lastShutImg) != -1)? contextRoot + opts.lastOpenImg: contextRoot + opts.openImg ;
      return ret ;
    });
    
    // 
    imgClicked.unbind('click') ;
    imgClicked.removeClass ("ajaximg") ;
    imgClicked.addClass ("parimg") ;
  }
  
  reBindClick = function (req, textStatus) {
    // TO-DO: bind click for new rows only
    bindClick () ;
  }

  reportError = function (XMLHttpRequest, textStatus, errorThrown) {
    alert ("Error during AJAX call: " + textStatus) ;
  }

  
  //
  expandOrCollapse = function(tr_row){
        // alert ("expand or collapse") ;
        if (tr_row.next().is(".collapsed")){//Then expand immediate children
          expandKids(tr_row);
        }else{//Collapse all and set image to opts.shutImg or opts.lastShutImg on parents
          collapseKidsLinear (tr_row);
        }
      }  
      
  // id_2_pid_1_type_Xyz -> 2
  parseId = function(num){
    var id = num.substring (3, num.indexOf ("_pid_")) ;
    
    return (id) ;    
  }
 
  parseParent = function(num){
    var parentId = num.substring (num.indexOf ("_pid_") + 5, num.indexOf ("_type_") ) ;
    
    return (parentId) ;    
  }
 
  parseType = function(num){
    var type = num.substring(num.indexOf ("_type_") + 6, num.indexOf ("_nextId_") ) ;
    
    return (type) ;    
  }
  
  parseNextId = function(num){
    var type = num.substring(num.indexOf ("_nextId_") + 8, num.indexOf ("_nextType_")) ;

    return (type) ;
  }

  parseNextType = function(num){
    var type = num.substring(num.indexOf ("_nextType_") + 10) ;

    return (type) ;
  }

  //Expands immediate children
  expandKids = function(tr_row){
    // alert ("expand") ;
    var num = tr_row.attr("id"); // id of the row
    var id = parseId (num) ;
    var type = parseType (num) ;
    var imgId = "img_" + type + "_" + id ;
    var attr_filter = "[id *= _pid_" + id + "_]"
    
    jq("#" + imgId).attr("src", function(){
      var ret = (this.src.lastIndexOf (opts.lastShutImg) != -1)? contextRoot + opts.lastOpenImg : contextRoot + opts.openImg ;
      return (ret) ;
    });
    
    jq(attr_filter).each(function(i){ 
      var $this = jq(this);
      $this.removeClass("collapsed");
    });
  };
  
  // it doesn't work'
  collapseKidsLinear = function(tr_row){
    var num = tr_row.attr("id"); // id of the row
    var id = parseId (num) ;
    var _type = parseType (num) ;

    var nextId = parseNextId (num) ;
    var nextType = parseNextType (num) ;

    // alert ("Collapse until row type: " + nextType + ", id: " + nextId) ;

    // actualiza la fila misma
    var imgId = "img_" + _type + "_" + id ;
    
    jq("#" + imgId).attr("src", function(){
      if (this.src.lastIndexOf (opts.lastShutImg) == -1){
        return (this.src.lastIndexOf (opts.lastOpenImg) != -1) ? contextRoot + opts.lastShutImg: contextRoot + opts.shutImg ;
      }
    });

    // esconde las filas descendientes (hijas, nietas, etc)
    tr_row.nextAll ("tr").each (function () {
      var nextRow = jq (this) ;
      var nextNum = nextRow.attr ("id") ;
      var _nextId = parseId (nextNum) ;
      var _nextType = parseType (nextNum) ;
          
      // termina cuando encontramos la fila signiente en la rama
      if (nextId == _nextId && nextType == _nextType )
        return (false) ;
    
      nextRow.addClass("collapsed");
    });

  }

  // Recursively collapses all children and their children and changes
  // works but too slow with big trees
  collapseKids = function(tr_row){
    var num = tr_row.attr("id"); // id of the row
    var id = parseId (num)
    var type = parseType (num) ;
    var imgId = "img_" + type + "_" + id ;
    
    // alert ("collapse num=" + num + " , id=" + id) ;

    jq("#" + imgId).attr("src", function(){
      if (this.src.lastIndexOf (opts.lastShutImg) == -1){
        return (this.src.lastIndexOf (opts.lastOpenImg) != -1) ? contextRoot + opts.lastShutImg: contextRoot + opts.shutImg ;
      }
    });
    
    var attr_filter = "[id *= _pid_" + id + "_]"
    
    jq(attr_filter).each(function(i){ 
      var $this = jq(this);
      $this.addClass("collapsed");
      collapseKids ($this) ;
    });
  };
 
})(jQuery);

